home *** CD-ROM | disk | FTP | other *** search
/ PC World 2008 September / PCWorld_2008-09_cd.bin / domacnost a kancelar / joomla / Joomla_1.5.4-Stable-Full_Package.exe / libraries / phpmailer / smtp.php < prev   
PHP Script  |  2008-07-06  |  34KB  |  1,046 lines

  1. <?php
  2. ////////////////////////////////////////////////////
  3. // SMTP - PHP SMTP class
  4. //
  5. // Version 1.02
  6. //
  7. // Define an SMTP class that can be used to connect
  8. // and communicate with any SMTP server. It implements
  9. // all the SMTP functions defined in RFC821 except TURN.
  10. //
  11. // Author: Chris Ryan
  12. //
  13. // License: LGPL, see LICENSE
  14. ////////////////////////////////////////////////////
  15.  
  16. /**
  17.  * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP
  18.  * commands except TURN which will always return a not implemented
  19.  * error. SMTP also provides some utility methods for sending mail
  20.  * to an SMTP server.
  21.  * @package PHPMailer
  22.  * @author Chris Ryan
  23.  */
  24. class SMTP
  25. {
  26.     /**
  27.      *  SMTP server port
  28.      *  @var int
  29.      */
  30.     var $SMTP_PORT = 25;
  31.  
  32.     /**
  33.      *  SMTP reply line ending
  34.      *  @var string
  35.      */
  36.     var $CRLF = "\r\n";
  37.  
  38.     /**
  39.      *  Sets whether debugging is turned on
  40.      *  @var bool
  41.      */
  42.     var $do_debug;       # the level of debug to perform
  43.  
  44.     /**#@+
  45.      * @access private
  46.      */
  47.     var $smtp_conn;      # the socket to the server
  48.     var $error;          # error if any on the last call
  49.     var $helo_rply;      # the reply the server sent to us for HELO
  50.     /**#@-*/
  51.  
  52.     /**
  53.      * Initialize the class so that the data is in a known state.
  54.      * @access public
  55.      * @return void
  56.      */
  57.     function SMTP() {
  58.         $this->smtp_conn = 0;
  59.         $this->error = null;
  60.         $this->helo_rply = null;
  61.  
  62.         $this->do_debug = 0;
  63.     }
  64.  
  65.     /*************************************************************
  66.      *                    CONNECTION FUNCTIONS                  *
  67.      ***********************************************************/
  68.  
  69.     /**
  70.      * Connect to the server specified on the port specified.
  71.      * If the port is not specified use the default SMTP_PORT.
  72.      * If tval is specified then a connection will try and be
  73.      * established with the server for that number of seconds.
  74.      * If tval is not specified the default is 30 seconds to
  75.      * try on the connection.
  76.      *
  77.      * SMTP CODE SUCCESS: 220
  78.      * SMTP CODE FAILURE: 421
  79.      * @access public
  80.      * @return bool
  81.      */
  82.     function Connect($host,$port=0,$tval=30) {
  83.         # set the error val to null so there is no confusion
  84.         $this->error = null;
  85.  
  86.         # make sure we are __not__ connected
  87.         if($this->connected()) {
  88.             # ok we are connected! what should we do?
  89.             # for now we will just give an error saying we
  90.             # are already connected
  91.             $this->error =
  92.                 array("error" => "Already connected to a server");
  93.             return false;
  94.         }
  95.  
  96.         if(empty($port)) {
  97.             $port = $this->SMTP_PORT;
  98.         }
  99.  
  100.         #connect to the smtp server
  101.         $this->smtp_conn = fsockopen($host,    # the host of the server
  102.                                      $port,    # the port to use
  103.                                      $errno,   # error number if any
  104.                                      $errstr,  # error message if any
  105.                                      $tval);   # give up after ? secs
  106.         # verify we connected properly
  107.         if(empty($this->smtp_conn)) {
  108.             $this->error = array("error" => "Failed to connect to server",
  109.                                  "errno" => $errno,
  110.                                  "errstr" => $errstr);
  111.             if($this->do_debug >= 1) {
  112.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  113.                          ": $errstr ($errno)" . $this->CRLF;
  114.             }
  115.             return false;
  116.         }
  117.  
  118.         # sometimes the SMTP server takes a little longer to respond
  119.         # so we will give it a longer timeout for the first read
  120.         // Windows still does not have support for this timeout function
  121.         if(substr(PHP_OS, 0, 3) != "WIN")
  122.            socket_set_timeout($this->smtp_conn, $tval, 0);
  123.  
  124.         # get any announcement stuff
  125.         $announce = $this->get_lines();
  126.  
  127.         # set the timeout  of any socket functions at 1/10 of a second
  128.         //if(function_exists("socket_set_timeout"))
  129.         //   socket_set_timeout($this->smtp_conn, 0, 100000);
  130.  
  131.         if($this->do_debug >= 2) {
  132.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $announce;
  133.         }
  134.  
  135.         return true;
  136.     }
  137.  
  138.     /**
  139.      * Performs SMTP authentication.  Must be run after running the
  140.      * Hello() method.  Returns true if successfully authenticated.
  141.      * @access public
  142.      * @return bool
  143.      */
  144.     function Authenticate($username, $password) {
  145.         // Start authentication
  146.         fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF);
  147.  
  148.         $rply = $this->get_lines();
  149.         $code = substr($rply,0,3);
  150.  
  151.         if($code != 334) {
  152.             $this->error =
  153.                 array("error" => "AUTH not accepted from server",
  154.                       "smtp_code" => $code,
  155.                       "smtp_msg" => substr($rply,4));
  156.             if($this->do_debug >= 1) {
  157.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  158.                          ": " . $rply . $this->CRLF;
  159.             }
  160.             return false;
  161.         }
  162.  
  163.         // Send encoded username
  164.         fputs($this->smtp_conn, base64_encode($username) . $this->CRLF);
  165.  
  166.         $rply = $this->get_lines();
  167.         $code = substr($rply,0,3);
  168.  
  169.         if($code != 334) {
  170.             $this->error =
  171.                 array("error" => "Username not accepted from server",
  172.                       "smtp_code" => $code,
  173.                       "smtp_msg" => substr($rply,4));
  174.             if($this->do_debug >= 1) {
  175.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  176.                          ": " . $rply . $this->CRLF;
  177.             }
  178.             return false;
  179.         }
  180.  
  181.         // Send encoded password
  182.         fputs($this->smtp_conn, base64_encode($password) . $this->CRLF);
  183.  
  184.         $rply = $this->get_lines();
  185.         $code = substr($rply,0,3);
  186.  
  187.         if($code != 235) {
  188.             $this->error =
  189.                 array("error" => "Password not accepted from server",
  190.                       "smtp_code" => $code,
  191.                       "smtp_msg" => substr($rply,4));
  192.             if($this->do_debug >= 1) {
  193.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  194.                          ": " . $rply . $this->CRLF;
  195.             }
  196.             return false;
  197.         }
  198.  
  199.         return true;
  200.     }
  201.  
  202.     /**
  203.      * Returns true if connected to a server otherwise false
  204.      * @access private
  205.      * @return bool
  206.      */
  207.     function Connected() {
  208.         if(!empty($this->smtp_conn)) {
  209.             $sock_status = socket_get_status($this->smtp_conn);
  210.             if($sock_status["eof"]) {
  211.                 # hmm this is an odd situation... the socket is
  212.                 # valid but we aren't connected anymore
  213.                 if($this->do_debug >= 1) {
  214.                     echo "SMTP -> NOTICE:" . $this->CRLF .
  215.                          "EOF caught while checking if connected";
  216.                 }
  217.                 $this->Close();
  218.                 return false;
  219.             }
  220.             return true; # everything looks good
  221.         }
  222.         return false;
  223.     }
  224.  
  225.     /**
  226.      * Closes the socket and cleans up the state of the class.
  227.      * It is not considered good to use this function without
  228.      * first trying to use QUIT.
  229.      * @access public
  230.      * @return void
  231.      */
  232.     function Close() {
  233.         $this->error = null; # so there is no confusion
  234.         $this->helo_rply = null;
  235.         if(!empty($this->smtp_conn)) {
  236.             # close the connection and cleanup
  237.             fclose($this->smtp_conn);
  238.             $this->smtp_conn = 0;
  239.         }
  240.     }
  241.  
  242.  
  243.     /***************************************************************
  244.      *                        SMTP COMMANDS                       *
  245.      *************************************************************/
  246.  
  247.     /**
  248.      * Issues a data command and sends the msg_data to the server
  249.      * finializing the mail transaction. $msg_data is the message
  250.      * that is to be send with the headers. Each header needs to be
  251.      * on a single line followed by a <CRLF> with the message headers
  252.      * and the message body being seperated by and additional <CRLF>.
  253.      *
  254.      * Implements rfc 821: DATA <CRLF>
  255.      *
  256.      * SMTP CODE INTERMEDIATE: 354
  257.      *     [data]
  258.      *     <CRLF>.<CRLF>
  259.      *     SMTP CODE SUCCESS: 250
  260.      *     SMTP CODE FAILURE: 552,554,451,452
  261.      * SMTP CODE FAILURE: 451,554
  262.      * SMTP CODE ERROR  : 500,501,503,421
  263.      * @access public
  264.      * @return bool
  265.      */
  266.     function Data($msg_data) {
  267.         $this->error = null; # so no confusion is caused
  268.  
  269.         if(!$this->connected()) {
  270.             $this->error = array(
  271.                     "error" => "Called Data() without being connected");
  272.             return false;
  273.         }
  274.  
  275.         fputs($this->smtp_conn,"DATA" . $this->CRLF);
  276.  
  277.         $rply = $this->get_lines();
  278.         $code = substr($rply,0,3);
  279.  
  280.         if($this->do_debug >= 2) {
  281.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  282.         }
  283.  
  284.         if($code != 354) {
  285.             $this->error =
  286.                 array("error" => "DATA command not accepted from server",
  287.                       "smtp_code" => $code,
  288.                       "smtp_msg" => substr($rply,4));
  289.             if($this->do_debug >= 1) {
  290.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  291.                          ": " . $rply . $this->CRLF;
  292.             }
  293.             return false;
  294.         }
  295.  
  296.         # the server is ready to accept data!
  297.         # according to rfc 821 we should not send more than 1000
  298.         # including the CRLF
  299.         # characters on a single line so we will break the data up
  300.         # into lines by \r and/or \n then if needed we will break
  301.         # each of those into smaller lines to fit within the limit.
  302.         # in addition we will be looking for lines that start with
  303.         # a period '.' and append and additional period '.' to that
  304.         # line. NOTE: this does not count towards are limit.
  305.  
  306.         # normalize the line breaks so we know the explode works
  307.         $msg_data = str_replace("\r\n","\n",$msg_data);
  308.         $msg_data = str_replace("\r","\n",$msg_data);
  309.         $lines = explode("\n",$msg_data);
  310.  
  311.         # we need to find a good way to determine is headers are
  312.         # in the msg_data or if it is a straight msg body
  313.         # currently I'm assuming rfc 822 definitions of msg headers
  314.         # and if the first field of the first line (':' sperated)
  315.         # does not contain a space then it _should_ be a header
  316.         # and we can process all lines before a blank "" line as
  317.         # headers.
  318.         $field = substr($lines[0],0,strpos($lines[0],":"));
  319.         $in_headers = false;
  320.         if(!empty($field) && !strstr($field," ")) {
  321.             $in_headers = true;
  322.         }
  323.  
  324.         $max_line_length = 998; # used below; set here for ease in change
  325.  
  326.         while(list(,$line) = @each($lines)) {
  327.             $lines_out = null;
  328.             if($line == "" && $in_headers) {
  329.                 $in_headers = false;
  330.             }
  331.             # ok we need to break this line up into several
  332.             # smaller lines
  333.             while(strlen($line) > $max_line_length) {
  334.                 $pos = strrpos(substr($line,0,$max_line_length)," ");
  335.  
  336.                 # Patch to fix DOS attack
  337.                 if(!$pos) {
  338.                     $pos = $max_line_length - 1;
  339.                 }
  340.  
  341.                 $lines_out[] = substr($line,0,$pos);
  342.                 $line = substr($line,$pos + 1);
  343.                 # if we are processing headers we need to
  344.                 # add a LWSP-char to the front of the new line
  345.                 # rfc 822 on long msg headers
  346.                 if($in_headers) {
  347.                     $line = "\t" . $line;
  348.                 }
  349.             }
  350.             $lines_out[] = $line;
  351.  
  352.             # now send the lines to the server
  353.             while(list(,$line_out) = @each($lines_out)) {
  354.                 if(strlen($line_out) > 0)
  355.                 {
  356.                     if(substr($line_out, 0, 1) == ".") {
  357.                         $line_out = "." . $line_out;
  358.                     }
  359.                 }
  360.                 fputs($this->smtp_conn,$line_out . $this->CRLF);
  361.             }
  362.         }
  363.  
  364.         # ok all the message data has been sent so lets get this
  365.         # over with aleady
  366.         fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
  367.  
  368.         $rply = $this->get_lines();
  369.         $code = substr($rply,0,3);
  370.  
  371.         if($this->do_debug >= 2) {
  372.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  373.         }
  374.  
  375.         if($code != 250) {
  376.             $this->error =
  377.                 array("error" => "DATA not accepted from server",
  378.                       "smtp_code" => $code,
  379.                       "smtp_msg" => substr($rply,4));
  380.             if($this->do_debug >= 1) {
  381.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  382.                          ": " . $rply . $this->CRLF;
  383.             }
  384.             return false;
  385.         }
  386.         return true;
  387.     }
  388.  
  389.     /**
  390.      * Expand takes the name and asks the server to list all the
  391.      * people who are members of the _list_. Expand will return
  392.      * back and array of the result or false if an error occurs.
  393.      * Each value in the array returned has the format of:
  394.      *     [ <full-name> <sp> ] <path>
  395.      * The definition of <path> is defined in rfc 821
  396.      *
  397.      * Implements rfc 821: EXPN <SP> <string> <CRLF>
  398.      *
  399.      * SMTP CODE SUCCESS: 250
  400.      * SMTP CODE FAILURE: 550
  401.      * SMTP CODE ERROR  : 500,501,502,504,421
  402.      * @access public
  403.      * @return string array
  404.      */
  405.     function Expand($name) {
  406.         $this->error = null; # so no confusion is caused
  407.  
  408.         if(!$this->connected()) {
  409.             $this->error = array(
  410.                     "error" => "Called Expand() without being connected");
  411.             return false;
  412.         }
  413.  
  414.         fputs($this->smtp_conn,"EXPN " . $name . $this->CRLF);
  415.  
  416.         $rply = $this->get_lines();
  417.         $code = substr($rply,0,3);
  418.  
  419.         if($this->do_debug >= 2) {
  420.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  421.         }
  422.  
  423.         if($code != 250) {
  424.             $this->error =
  425.                 array("error" => "EXPN not accepted from server",
  426.                       "smtp_code" => $code,
  427.                       "smtp_msg" => substr($rply,4));
  428.             if($this->do_debug >= 1) {
  429.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  430.                          ": " . $rply . $this->CRLF;
  431.             }
  432.             return false;
  433.         }
  434.  
  435.         # parse the reply and place in our array to return to user
  436.         $entries = explode($this->CRLF,$rply);
  437.         while(list(,$l) = @each($entries)) {
  438.             $list[] = substr($l,4);
  439.         }
  440.  
  441.         return $list;
  442.     }
  443.  
  444.     /**
  445.      * Sends the HELO command to the smtp server.
  446.      * This makes sure that we and the server are in
  447.      * the same known state.
  448.      *
  449.      * Implements from rfc 821: HELO <SP> <domain> <CRLF>
  450.      *
  451.      * SMTP CODE SUCCESS: 250
  452.      * SMTP CODE ERROR  : 500, 501, 504, 421
  453.      * @access public
  454.      * @return bool
  455.      */
  456.     function Hello($host="") {
  457.         $this->error = null; # so no confusion is caused
  458.  
  459.         if(!$this->connected()) {
  460.             $this->error = array(
  461.                     "error" => "Called Hello() without being connected");
  462.             return false;
  463.         }
  464.  
  465.         # if a hostname for the HELO wasn't specified determine
  466.         # a suitable one to send
  467.         if(empty($host)) {
  468.             # we need to determine some sort of appopiate default
  469.             # to send to the server
  470.             $host = "localhost";
  471.         }
  472.  
  473.         // Send extended hello first (RFC 2821)
  474.         if(!$this->SendHello("EHLO", $host))
  475.         {
  476.             if(!$this->SendHello("HELO", $host))
  477.                 return false;
  478.         }
  479.  
  480.         return true;
  481.     }
  482.  
  483.     /**
  484.      * Sends a HELO/EHLO command.
  485.      * @access private
  486.      * @return bool
  487.      */
  488.     function SendHello($hello, $host) {
  489.         fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);
  490.  
  491.         $rply = $this->get_lines();
  492.         $code = substr($rply,0,3);
  493.  
  494.         if($this->do_debug >= 2) {
  495.             echo "SMTP -> FROM SERVER: " . $this->CRLF . $rply;
  496.         }
  497.  
  498.         if($code != 250) {
  499.             $this->error =
  500.                 array("error" => $hello . " not accepted from server",
  501.                       "smtp_code" => $code,
  502.                       "smtp_msg" => substr($rply,4));
  503.             if($this->do_debug >= 1) {
  504.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  505.                          ": " . $rply . $this->CRLF;
  506.             }
  507.             return false;
  508.         }
  509.  
  510.         $this->helo_rply = $rply;
  511.  
  512.         return true;
  513.     }
  514.  
  515.     /**
  516.      * Gets help information on the keyword specified. If the keyword
  517.      * is not specified then returns generic help, ussually contianing
  518.      * A list of keywords that help is available on. This function
  519.      * returns the results back to the user. It is up to the user to
  520.      * handle the returned data. If an error occurs then false is
  521.      * returned with $this->error set appropiately.
  522.      *
  523.      * Implements rfc 821: HELP [ <SP> <string> ] <CRLF>
  524.      *
  525.      * SMTP CODE SUCCESS: 211,214
  526.      * SMTP CODE ERROR  : 500,501,502,504,421
  527.      * @access public
  528.      * @return string
  529.      */
  530.     function Help($keyword="") {
  531.         $this->error = null; # to avoid confusion
  532.  
  533.         if(!$this->connected()) {
  534.             $this->error = array(
  535.                     "error" => "Called Help() without being connected");
  536.             return false;
  537.         }
  538.  
  539.         $extra = "";
  540.         if(!empty($keyword)) {
  541.             $extra = " " . $keyword;
  542.         }
  543.  
  544.         fputs($this->smtp_conn,"HELP" . $extra . $this->CRLF);
  545.  
  546.         $rply = $this->get_lines();
  547.         $code = substr($rply,0,3);
  548.  
  549.         if($this->do_debug >= 2) {
  550.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  551.         }
  552.  
  553.         if($code != 211 && $code != 214) {
  554.             $this->error =
  555.                 array("error" => "HELP not accepted from server",
  556.                       "smtp_code" => $code,
  557.                       "smtp_msg" => substr($rply,4));
  558.             if($this->do_debug >= 1) {
  559.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  560.                          ": " . $rply . $this->CRLF;
  561.             }
  562.             return false;
  563.         }
  564.  
  565.         return $rply;
  566.     }
  567.  
  568.     /**
  569.      * Starts a mail transaction from the email address specified in
  570.      * $from. Returns true if successful or false otherwise. If True
  571.      * the mail transaction is started and then one or more Recipient
  572.      * commands may be called followed by a Data command.
  573.      *
  574.      * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
  575.      *
  576.      * SMTP CODE SUCCESS: 250
  577.      * SMTP CODE SUCCESS: 552,451,452
  578.      * SMTP CODE SUCCESS: 500,501,421
  579.      * @access public
  580.      * @return bool
  581.      */
  582.     function Mail($from) {
  583.         $this->error = null; # so no confusion is caused
  584.  
  585.         if(!$this->connected()) {
  586.             $this->error = array(
  587.                     "error" => "Called Mail() without being connected");
  588.             return false;
  589.         }
  590.  
  591.         fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $this->CRLF);
  592.  
  593.         $rply = $this->get_lines();
  594.         $code = substr($rply,0,3);
  595.  
  596.         if($this->do_debug >= 2) {
  597.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  598.         }
  599.  
  600.         if($code != 250) {
  601.             $this->error =
  602.                 array("error" => "MAIL not accepted from server",
  603.                       "smtp_code" => $code,
  604.                       "smtp_msg" => substr($rply,4));
  605.             if($this->do_debug >= 1) {
  606.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  607.                          ": " . $rply . $this->CRLF;
  608.             }
  609.             return false;
  610.         }
  611.         return true;
  612.     }
  613.  
  614.     /**
  615.      * Sends the command NOOP to the SMTP server.
  616.      *
  617.      * Implements from rfc 821: NOOP <CRLF>
  618.      *
  619.      * SMTP CODE SUCCESS: 250
  620.      * SMTP CODE ERROR  : 500, 421
  621.      * @access public
  622.      * @return bool
  623.      */
  624.     function Noop() {
  625.         $this->error = null; # so no confusion is caused
  626.  
  627.         if(!$this->connected()) {
  628.             $this->error = array(
  629.                     "error" => "Called Noop() without being connected");
  630.             return false;
  631.         }
  632.  
  633.         fputs($this->smtp_conn,"NOOP" . $this->CRLF);
  634.  
  635.         $rply = $this->get_lines();
  636.         $code = substr($rply,0,3);
  637.  
  638.         if($this->do_debug >= 2) {
  639.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  640.         }
  641.  
  642.         if($code != 250) {
  643.             $this->error =
  644.                 array("error" => "NOOP not accepted from server",
  645.                       "smtp_code" => $code,
  646.                       "smtp_msg" => substr($rply,4));
  647.             if($this->do_debug >= 1) {
  648.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  649.                          ": " . $rply . $this->CRLF;
  650.             }
  651.             return false;
  652.         }
  653.         return true;
  654.     }
  655.  
  656.     /**
  657.      * Sends the quit command to the server and then closes the socket
  658.      * if there is no error or the $close_on_error argument is true.
  659.      *
  660.      * Implements from rfc 821: QUIT <CRLF>
  661.      *
  662.      * SMTP CODE SUCCESS: 221
  663.      * SMTP CODE ERROR  : 500
  664.      * @access public
  665.      * @return bool
  666.      */
  667.     function Quit($close_on_error=true) {
  668.         $this->error = null; # so there is no confusion
  669.  
  670.         if(!$this->connected()) {
  671.             $this->error = array(
  672.                     "error" => "Called Quit() without being connected");
  673.             return false;
  674.         }
  675.  
  676.         # send the quit command to the server
  677.         fputs($this->smtp_conn,"quit" . $this->CRLF);
  678.  
  679.         # get any good-bye messages
  680.         $byemsg = $this->get_lines();
  681.  
  682.         if($this->do_debug >= 2) {
  683.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $byemsg;
  684.         }
  685.  
  686.         $rval = true;
  687.         $e = null;
  688.  
  689.         $code = substr($byemsg,0,3);
  690.         if($code != 221) {
  691.             # use e as a tmp var cause Close will overwrite $this->error
  692.             $e = array("error" => "SMTP server rejected quit command",
  693.                        "smtp_code" => $code,
  694.                        "smtp_rply" => substr($byemsg,4));
  695.             $rval = false;
  696.             if($this->do_debug >= 1) {
  697.                 echo "SMTP -> ERROR: " . $e["error"] . ": " .
  698.                          $byemsg . $this->CRLF;
  699.             }
  700.         }
  701.  
  702.         if(empty($e) || $close_on_error) {
  703.             $this->Close();
  704.         }
  705.  
  706.         return $rval;
  707.     }
  708.  
  709.     /**
  710.      * Sends the command RCPT to the SMTP server with the TO: argument of $to.
  711.      * Returns true if the recipient was accepted false if it was rejected.
  712.      *
  713.      * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
  714.      *
  715.      * SMTP CODE SUCCESS: 250,251
  716.      * SMTP CODE FAILURE: 550,551,552,553,450,451,452
  717.      * SMTP CODE ERROR  : 500,501,503,421
  718.      * @access public
  719.      * @return bool
  720.      */
  721.     function Recipient($to) {
  722.         $this->error = null; # so no confusion is caused
  723.  
  724.         if(!$this->connected()) {
  725.             $this->error = array(
  726.                     "error" => "Called Recipient() without being connected");
  727.             return false;
  728.         }
  729.  
  730.         fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF);
  731.  
  732.         $rply = $this->get_lines();
  733.         $code = substr($rply,0,3);
  734.  
  735.         if($this->do_debug >= 2) {
  736.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  737.         }
  738.  
  739.         if($code != 250 && $code != 251) {
  740.             $this->error =
  741.                 array("error" => "RCPT not accepted from server",
  742.                       "smtp_code" => $code,
  743.                       "smtp_msg" => substr($rply,4));
  744.             if($this->do_debug >= 1) {
  745.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  746.                          ": " . $rply . $this->CRLF;
  747.             }
  748.             return false;
  749.         }
  750.         return true;
  751.     }
  752.  
  753.     /**
  754.      * Sends the RSET command to abort and transaction that is
  755.      * currently in progress. Returns true if successful false
  756.      * otherwise.
  757.      *
  758.      * Implements rfc 821: RSET <CRLF>
  759.      *
  760.      * SMTP CODE SUCCESS: 250
  761.      * SMTP CODE ERROR  : 500,501,504,421
  762.      * @access public
  763.      * @return bool
  764.      */
  765.     function Reset() {
  766.         $this->error = null; # so no confusion is caused
  767.  
  768.         if(!$this->connected()) {
  769.             $this->error = array(
  770.                     "error" => "Called Reset() without being connected");
  771.             return false;
  772.         }
  773.  
  774.         fputs($this->smtp_conn,"RSET" . $this->CRLF);
  775.  
  776.         $rply = $this->get_lines();
  777.         $code = substr($rply,0,3);
  778.  
  779.         if($this->do_debug >= 2) {
  780.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  781.         }
  782.  
  783.         if($code != 250) {
  784.             $this->error =
  785.                 array("error" => "RSET failed",
  786.                       "smtp_code" => $code,
  787.                       "smtp_msg" => substr($rply,4));
  788.             if($this->do_debug >= 1) {
  789.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  790.                          ": " . $rply . $this->CRLF;
  791.             }
  792.             return false;
  793.         }
  794.  
  795.         return true;
  796.     }
  797.  
  798.     /**
  799.      * Starts a mail transaction from the email address specified in
  800.      * $from. Returns true if successful or false otherwise. If True
  801.      * the mail transaction is started and then one or more Recipient
  802.      * commands may be called followed by a Data command. This command
  803.      * will send the message to the users terminal if they are logged
  804.      * in.
  805.      *
  806.      * Implements rfc 821: SEND <SP> FROM:<reverse-path> <CRLF>
  807.      *
  808.      * SMTP CODE SUCCESS: 250
  809.      * SMTP CODE SUCCESS: 552,451,452
  810.      * SMTP CODE SUCCESS: 500,501,502,421
  811.      * @access public
  812.      * @return bool
  813.      */
  814.     function Send($from) {
  815.         $this->error = null; # so no confusion is caused
  816.  
  817.         if(!$this->connected()) {
  818.             $this->error = array(
  819.                     "error" => "Called Send() without being connected");
  820.             return false;
  821.         }
  822.  
  823.         fputs($this->smtp_conn,"SEND FROM:" . $from . $this->CRLF);
  824.  
  825.         $rply = $this->get_lines();
  826.         $code = substr($rply,0,3);
  827.  
  828.         if($this->do_debug >= 2) {
  829.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  830.         }
  831.  
  832.         if($code != 250) {
  833.             $this->error =
  834.                 array("error" => "SEND not accepted from server",
  835.                       "smtp_code" => $code,
  836.                       "smtp_msg" => substr($rply,4));
  837.             if($this->do_debug >= 1) {
  838.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  839.                          ": " . $rply . $this->CRLF;
  840.             }
  841.             return false;
  842.         }
  843.         return true;
  844.     }
  845.  
  846.     /**
  847.      * Starts a mail transaction from the email address specified in
  848.      * $from. Returns true if successful or false otherwise. If True
  849.      * the mail transaction is started and then one or more Recipient
  850.      * commands may be called followed by a Data command. This command
  851.      * will send the message to the users terminal if they are logged
  852.      * in and send them an email.
  853.      *
  854.      * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
  855.      *
  856.      * SMTP CODE SUCCESS: 250
  857.      * SMTP CODE SUCCESS: 552,451,452
  858.      * SMTP CODE SUCCESS: 500,501,502,421
  859.      * @access public
  860.      * @return bool
  861.      */
  862.     function SendAndMail($from) {
  863.         $this->error = null; # so no confusion is caused
  864.  
  865.         if(!$this->connected()) {
  866.             $this->error = array(
  867.                 "error" => "Called SendAndMail() without being connected");
  868.             return false;
  869.         }
  870.  
  871.         fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);
  872.  
  873.         $rply = $this->get_lines();
  874.         $code = substr($rply,0,3);
  875.  
  876.         if($this->do_debug >= 2) {
  877.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  878.         }
  879.  
  880.         if($code != 250) {
  881.             $this->error =
  882.                 array("error" => "SAML not accepted from server",
  883.                       "smtp_code" => $code,
  884.                       "smtp_msg" => substr($rply,4));
  885.             if($this->do_debug >= 1) {
  886.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  887.                          ": " . $rply . $this->CRLF;
  888.             }
  889.             return false;
  890.         }
  891.         return true;
  892.     }
  893.  
  894.     /**
  895.      * Starts a mail transaction from the email address specified in
  896.      * $from. Returns true if successful or false otherwise. If True
  897.      * the mail transaction is started and then one or more Recipient
  898.      * commands may be called followed by a Data command. This command
  899.      * will send the message to the users terminal if they are logged
  900.      * in or mail it to them if they are not.
  901.      *
  902.      * Implements rfc 821: SOML <SP> FROM:<reverse-path> <CRLF>
  903.      *
  904.      * SMTP CODE SUCCESS: 250
  905.      * SMTP CODE SUCCESS: 552,451,452
  906.      * SMTP CODE SUCCESS: 500,501,502,421
  907.      * @access public
  908.      * @return bool
  909.      */
  910.     function SendOrMail($from) {
  911.         $this->error = null; # so no confusion is caused
  912.  
  913.         if(!$this->connected()) {
  914.             $this->error = array(
  915.                 "error" => "Called SendOrMail() without being connected");
  916.             return false;
  917.         }
  918.  
  919.         fputs($this->smtp_conn,"SOML FROM:" . $from . $this->CRLF);
  920.  
  921.         $rply = $this->get_lines();
  922.         $code = substr($rply,0,3);
  923.  
  924.         if($this->do_debug >= 2) {
  925.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  926.         }
  927.  
  928.         if($code != 250) {
  929.             $this->error =
  930.                 array("error" => "SOML not accepted from server",
  931.                       "smtp_code" => $code,
  932.                       "smtp_msg" => substr($rply,4));
  933.             if($this->do_debug >= 1) {
  934.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  935.                          ": " . $rply . $this->CRLF;
  936.             }
  937.             return false;
  938.         }
  939.         return true;
  940.     }
  941.  
  942.     /**
  943.      * This is an optional command for SMTP that this class does not
  944.      * support. This method is here to make the RFC821 Definition
  945.      * complete for this class and __may__ be implimented in the future
  946.      *
  947.      * Implements from rfc 821: TURN <CRLF>
  948.      *
  949.      * SMTP CODE SUCCESS: 250
  950.      * SMTP CODE FAILURE: 502
  951.      * SMTP CODE ERROR  : 500, 503
  952.      * @access public
  953.      * @return bool
  954.      */
  955.     function Turn() {
  956.         $this->error = array("error" => "This method, TURN, of the SMTP ".
  957.                                         "is not implemented");
  958.         if($this->do_debug >= 1) {
  959.             echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF;
  960.         }
  961.         return false;
  962.     }
  963.  
  964.     /**
  965.      * Verifies that the name is recognized by the server.
  966.      * Returns false if the name could not be verified otherwise
  967.      * the response from the server is returned.
  968.      *
  969.      * Implements rfc 821: VRFY <SP> <string> <CRLF>
  970.      *
  971.      * SMTP CODE SUCCESS: 250,251
  972.      * SMTP CODE FAILURE: 550,551,553
  973.      * SMTP CODE ERROR  : 500,501,502,421
  974.      * @access public
  975.      * @return int
  976.      */
  977.     function Verify($name) {
  978.         $this->error = null; # so no confusion is caused
  979.  
  980.         if(!$this->connected()) {
  981.             $this->error = array(
  982.                     "error" => "Called Verify() without being connected");
  983.             return false;
  984.         }
  985.  
  986.         fputs($this->smtp_conn,"VRFY " . $name . $this->CRLF);
  987.  
  988.         $rply = $this->get_lines();
  989.         $code = substr($rply,0,3);
  990.  
  991.         if($this->do_debug >= 2) {
  992.             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
  993.         }
  994.  
  995.         if($code != 250 && $code != 251) {
  996.             $this->error =
  997.                 array("error" => "VRFY failed on name '$name'",
  998.                       "smtp_code" => $code,
  999.                       "smtp_msg" => substr($rply,4));
  1000.             if($this->do_debug >= 1) {
  1001.                 echo "SMTP -> ERROR: " . $this->error["error"] .
  1002.                          ": " . $rply . $this->CRLF;
  1003.             }
  1004.             return false;
  1005.         }
  1006.         return $rply;
  1007.     }
  1008.  
  1009.     /*******************************************************************
  1010.      *                       INTERNAL FUNCTIONS                       *
  1011.      ******************************************************************/
  1012.  
  1013.     /**
  1014.      * Read in as many lines as possible
  1015.      * either before eof or socket timeout occurs on the operation.
  1016.      * With SMTP we can tell if we have more lines to read if the
  1017.      * 4th character is '-' symbol. If it is a space then we don't
  1018.      * need to read anything else.
  1019.      * @access private
  1020.      * @return string
  1021.      */
  1022.     function get_lines() {
  1023.         $data = "";
  1024.         while($str = fgets($this->smtp_conn,515)) {
  1025.             if($this->do_debug >= 4) {
  1026.                 echo "SMTP -> get_lines(): \$data was \"$data\"" .
  1027.                          $this->CRLF;
  1028.                 echo "SMTP -> get_lines(): \$str is \"$str\"" .
  1029.                          $this->CRLF;
  1030.             }
  1031.             $data .= $str;
  1032.             if($this->do_debug >= 4) {
  1033.                 echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF;
  1034.             }
  1035.             # if the 4th character is a space then we are done reading
  1036.             # so just break the loop
  1037.             if(substr($str,3,1) == " ") { break; }
  1038.         }
  1039.         return $data;
  1040.     }
  1041.  
  1042. }
  1043.  
  1044.  
  1045.  ?>
  1046.